package com.chapter07.dao;

import com.bdqn.util.JDBCUtils;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public abstract class BaseDao<T> {

    private Class<T> clazz;

    // 使用非静态代码块，给clazz赋值
    {
        // 获取父类的泛型
        Type genericSuperclass = this.getClass().getGenericSuperclass();
        ParameterizedType paramType = (ParameterizedType) genericSuperclass;

        // 获取父类泛型的实际参数
        Type[] typeArguments = paramType.getActualTypeArguments();
        clazz = (Class<T>) typeArguments[0];
    }

    public int update(Connection connection, String sql, Object... objs) {
        int result = 0;
        PreparedStatement preparedStatement = null;
        try {
            preparedStatement = connection.prepareStatement(sql);
            if (objs.length > 0) { // 参数的个数有
                for (int i = 0; i < objs.length; i++) {
                    preparedStatement.setObject(i + 1, objs[i]);
                }
            }
            result = preparedStatement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.closeResource(connection, preparedStatement, null);
        }
        return result;
    }

    public List<T> query(Connection connection, String sql, Object... objs) {
        List<T> list = new ArrayList<>();
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {
            preparedStatement = connection.prepareStatement(sql);
            resultSet = preparedStatement.executeQuery();
            ResultSetMetaData rsmd = resultSet.getMetaData();
            int columnCount = rsmd.getColumnCount();

            while (resultSet.next()) {
                // 通过反射的方式创建了一个grade对象
                T t = clazz.newInstance();
                for (int i = 0; i < columnCount; i++) {
                    // 拿到每一列的值
                    Object objValue = resultSet.getObject(i + 1);
                    // 可以拿到列的名称
                    String columnLabel = rsmd.getColumnLabel(i + 1);
                    // 拿到一个字段
                    Field field = clazz.getDeclaredField(columnLabel);
                    field.setAccessible(true);
                    field.set(t, objValue);
                }
                list.add(t);
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.closeResource(connection, preparedStatement, resultSet);
        }
        return list;
    }


    public T getSingletonEntity(Connection connection, String sql, Object... objs) throws IllegalAccessException, InstantiationException {
        // 通过反射的方式创建了一个grade对象
        T t = clazz.newInstance();
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {
            preparedStatement = connection.prepareStatement(sql);
            if (objs.length > 0) { // 参数的个数有
                for (int i = 0; i < objs.length; i++) {
                    preparedStatement.setObject(i + 1, objs[i]);
                }
            }

            resultSet = preparedStatement.executeQuery();
            ResultSetMetaData rsmd = resultSet.getMetaData();
            int columnCount = rsmd.getColumnCount();

            if (resultSet.next()) {

                for (int i = 0; i < columnCount; i++) {
                    // 拿到每一列的值
                    Object objValue = resultSet.getObject(i + 1);
                    // 可以拿到列的名称
                    String columnLabel = rsmd.getColumnLabel(i + 1);
                    // 拿到一个字段
                    Field field = clazz.getDeclaredField(columnLabel);
                    field.setAccessible(true);
                    field.set(t, objValue);
                }
            }
            return t;
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.closeResource(connection, preparedStatement, resultSet);
        }
        return null;
    }

}
